/**
 * 给定N个点，每个点有目标权值Ai，初始权值为零
 * 给定M条候选边。做如下操作：
 * 1. 可以选择一条没有用过的侯选边，进行连边
 * 2. 选择一个连通子图将所有点的当前权值加1
 * 目标是使得每个点的权值恰好等于Ai，问所需的操作2的最少次数
 * 操作1可以最多进行min(5N, M)次。
 * 注意到如果候选边允许的话，将整个图连通的操作1数量为N-1，所以操作1的限制可以无需考虑
 * 专心考虑操作2即可
 * 
 * 由于累加有Ai的限制，因此我们应该先将权值大的节点加到一定程度，再把权值小的节点加入连通块累加
 * 再加到一定程度，再把更小的点加入连通块
 * 
 * 这样考虑比较麻烦，倒过来考虑。令初始权值为Ai，进行减法，减到零即可。答案是一样的。
 * 如此操作，则连通块上所有的点的权值均相等，称作连通块的权值，一起往下减。
 * 对当前连通块，在所有邻点中选择权值小于当前连通块的最大值，将其合并，且差值加入答案。
 * 但这个顺序比较麻烦，采用另外一种顺序。按权值的顺序。
 * 对某个连通块，假设其权值是W，则不必关心其邻居，W总是要往下减的，
 * 直到减到某个邻居，将该邻居并进来即可
 * 
 * 将权值从大到小排序
 * 令当前权值是cur，当前连通块的数量是cnt，下一个权值是target
 * 则令 ans += cnt * (cur - target) 即可
 * 唯一的问题是维护cnt
 * 使用并查集即可    
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using pii = pair<int, int>;

struct uf_t{
vi father, rank;
void init(int n){
    father.assign(n + 1, 0);for(int i=1;i<=n;++i)father[i]=i;
}
int find(int x){
    return x == father[x] ? x : father[x] = find(father[x]);
}
void unite(int x, int y){
    y = find(y);
    x = find(x);
    father[y] = x;
}

}UF;

int N;
int M;
vi A;
vector<vi> G;

llt proc(){
    map<int, vi> mm;
    for(int i=1;i<=N;++i){
        mm[A[i]].emplace_back(i);
    }    
    
    UF.init(N + 1);
    if(not mm.count(0)){
        mm[0].emplace_back(N + 1);
    }
    
    llt ans = 0;
    int cnt = 0;
    for(auto it=mm.rbegin(),et=--mm.rend();it!=et;++it){
        auto jt = ++it; -- it;
        auto target = jt->first;
        auto cur = it->first;
        llt cha = cur - target;

        cnt += it->second.size();
        for(auto i : it->second){
            for(auto v : G[i]){  
                auto fi = UF.find(i);
                auto fv = UF.find(v);
                if(fi == fv) continue;
                if(A[fv] >= cur){
                    --cnt;
                    UF.father[fv] = fi;
                }   
            }
        }

        ans += cha * cnt;
    }

    return ans;
}

void work(){
    cin >> N >> M;
    A.assign(N + 1, {});
    for(int i=1;i<=N;++i) cin >> A[i];

    G.assign(N + 2, {});
    UF.init(N + 2);
    for(int a,b,i=0;i<M;++i){
        cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    cout << proc() << endl;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--){	
        work();
	}
    return 0;
}